package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.CommonCodeMsg;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.feign.ProductFeignApi;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCommand;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
@Slf4j
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ProductFeignApi productFeignApi;

    @Override
    public List<SeckillProductVo> selectByTime(Integer time) {
        //查询出秒杀商品的列表
        List<SeckillProduct> seckillProductList = seckillProductMapper.queryCurrentlySeckillProduct(time);
        if (seckillProductList == null || seckillProductList.size() == 0){
            log.error("【秒杀商品服务】：秒杀商品查询为空=》{}", seckillProductList);
            return Collections.emptyList();
        }
        //将查询到的秒杀商品Id存储到Set
        Set<Long> productIds = new HashSet<>();
        seckillProductList.forEach(seckillProduct -> productIds.add(seckillProduct.getProductId()));
        //调用Feign接口实现服务之间的调用
        Result<List<Product>> listResult = productFeignApi.selectProductByIds(productIds);
        List<Product> productList = listResult.getData();
        //判空抛异常
        if (productList == null || listResult.hasError()) {
            log.error("【秒杀商品服务】：商品查询异常=》{}",productList);
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
        //将查出来的列表存储到map中
        Map<Long, Product> productMap = new HashMap<>();
        productList.forEach(product -> productMap.put(product.getId(),product));
        List<SeckillProductVo> list = new ArrayList<>();
        //将两个列表的两个对象copy到vo对象
        seckillProductList.forEach(seckillProduct -> {
            SeckillProductVo seckillProductVo = new SeckillProductVo();
            BeanUtils.copyProperties(productMap.get(seckillProduct.getProductId()),seckillProductVo);
            BeanUtils.copyProperties(seckillProduct,seckillProductVo);
            list.add(seckillProductVo);
        });
        return list;
    }

    @Override
    public SeckillProductVo queryByTimeAndSeckillId(String time,String seckillId) {
        Object seckillVo = redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(time), seckillId);
        if (seckillVo == null){
            log.error("【秒杀商品服务】：从redis查询商品异常");
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
        return JSON.parseObject(String.valueOf(seckillVo),SeckillProductVo.class);
    }

    @Override
    public List<SeckillProductVo> selectByTimeFromRedis(Integer time) {
        List<Object> values = redisTemplate.opsForHash().values(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(String.valueOf(time)));
        if (values.size() == 0){
            log.warn("【秒杀商品服务】：从Redis获取商品异常");
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
        List<SeckillProductVo> seckillProductVoList = new ArrayList<>();
        values.forEach(s->{
            SeckillProductVo seckillProductVo = JSON.parseObject(String.valueOf(s), SeckillProductVo.class);
            seckillProductVoList.add(seckillProductVo);
        });
        return  seckillProductVoList;
    }

    @Override
    public void decrStockCount(SeckillProductVo seckillProductVo) {
        int i = seckillProductMapper.decrStock(seckillProductVo.getId());
        if (i > 0){
            //扣除Redis库存
            seckillProductVo.setCurrentCount(seckillProductVo.getStockCount() - 1);
            String realKey = SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(seckillProductVo.getTime() + "");
            redisTemplate.opsForHash().put(realKey,seckillProductVo.getId() + "", JSON.toJSONString(seckillProductVo));
        }
    }
}
